library(here)
library(readxl)
#library(papeR)
#library(outliers)
library(kableExtra)
#library(DataExplorer)
library(lubridate)
library(forecast)

Attaching package: ‘forecast’

The following object is masked from ‘package:yardstick’:

    accuracy
library(nlme)

Attaching package: ‘nlme’

The following object is masked from ‘package:forecast’:

    getResponse

The following object is masked from ‘package:dplyr’:

    collapse
#library(nortest)
library(ggfortify)
Registered S3 methods overwritten by 'ggfortify':
  method                 from    
  autoplot.Arima         forecast
  autoplot.acf           forecast
  autoplot.ar            forecast
  autoplot.bats          forecast
  autoplot.decomposed.ts forecast
  autoplot.ets           forecast
  autoplot.forecast      forecast
  autoplot.stl           forecast
  autoplot.ts            forecast
  fitted.ar              forecast
  fortify.ts             forecast
  residuals.ar           forecast
library(dygraphs)
#library(seasonal)
#library(seasonalview)

library(nonlinearTseries)

Attaching package: ‘nonlinearTseries’

The following object is masked from ‘package:grDevices’:

    contourLines
library(fNonlinear)
Loading required package: timeDate

Attaching package: ‘timeDate’

The following objects are masked from ‘package:PerformanceAnalytics’:

    kurtosis, skewness

Loading required package: timeSeries

Attaching package: ‘timeSeries’

The following object is masked from ‘package:zoo’:

    time<-

Loading required package: fBasics

Attaching package: ‘fBasics’

The following object is masked from ‘package:TTR’:

    volatility


Attaching package: ‘fNonlinear’

The following object is masked from ‘package:nonlinearTseries’:

    recurrencePlot
library(fGarch)
library(TSA)

Attaching package: ‘TSA’

The following objects are masked from ‘package:timeDate’:

    kurtosis, skewness

The following objects are masked from ‘package:PerformanceAnalytics’:

    kurtosis, skewness

The following object is masked from ‘package:readr’:

    spec

The following object is masked from ‘package:yardstick’:

    spec

The following objects are masked from ‘package:stats’:

    acf, arima

The following object is masked from ‘package:utils’:

    tar
library(tsDyn)

library(tidyverse)

Rutas

raw_data <- here("data", "raw")
interim_data <- here("data", "interim")
final_data <- here("data", "processed")

Leyendo base de datos

base <- read_excel(paste0(raw_data,"/Base Datos.xlsx"), 
    col_types = c("text", "numeric", "numeric"))

head(base)

Extrayendo la base de colones y de dolares


colones <- data_frame(date = base$`Activo neto`,
                  col =  as.double(base$CRC)) %>%
  mutate(date = ymd(paste0(date, "-01"))) %>%
  mutate(year = as.factor(year(date)),
         month = as.factor(month(date)))

head(colones)

Convirtiendo los datos a series de tiempo

# Colones

# 6 periodos para utilizar a modo de validación
colones_val <- colones %>% 
  slice_tail(n = 6)

# Serie completa para el analisis exploratorio
colones_full <- colones

# 10 años de datos para modelar
colones <- colones %>% 
  filter(date>"2007-12-01" & date<="2020-01-01")

# Objetos ts tanto para la serie completa como para la serie de modelado
colones_ts_full <- ts(colones_full$col, start = c(2001,2), frequency = 12)
colones_ts <- ts(colones$col, start = c(2008,1), frequency = 12)
colones_ts_val <- tail(colones_ts_full, 6)

1 Comprobacion de linealidad de la serie

1.1 Prueba de linealidad de la media


# Null hypothesis: Linearity in "mean"
tnnTest(colones_ts, lag = 1, title = NULL, description = NULL)

Title:
 Teraesvirta Neural Network Test

Test Results:
  PARAMETER:
    lag: 1
    m|df: 2
    t-lag-m|df: 142
  STATISTIC:
    Chi-squared: 7.9259
    F: 3.989
  P VALUE:
    Chi-squared: 0.01901 
    F: 0.02063 

Description:
 Thu Sep 10 20:06:28 2020 by user: 

La hipótesis nula del Teraesvirta Neural Network Test es que la media de la serie es lineal. Al rechazarse la hipótesis con una confianza del 95% se puede decir que la serie es no lineal.

1.2 Prueba para determinar si es caotica o no

options(max.print=1000000)
rqa.analysis=rqa(time.series = colones_ts, embedding.dim=1, time.lag=1,radius=0.01,lmin=2,vmin=2,do.plot=TRUE,distanceToBorder=2)

2. Inspección

# Una forma visual de empezar a revisar si existen o no clusters de volatilidad 

colones_ts_nd <-diff(log(colones_ts))


colones_ts_nd2<-colones_ts_nd-mean(colones_ts_nd) # Es el cambio relativo ajustado por la media en el tipo de cambio 
#colones_ts_nd2

colones_ts_nd3<-colones_ts_nd2^2 # Medida de la volatilidad. Al ser una cantidad al cuadrado, su valor ser? alto en periodos en que se experimenten grandes cambios  y comparativamente peque?o cuando sucedan cambios modestos en los precios de dichos bienes. 

plot(colones_ts_nd3)

En este gráfico de la serie ajustada por la media y elevada al cuadrado se pretende observar la volatilidad de la misma. Al ser una cantidad al cuadrado, cuando su valor ses alto en indica que se experimenten grandes cambios y comparativamente pequeño cuando sucedan cambios modestos en los precios de dichos bienes. Es así que es claro que después del 2008, alrededor del 2014 y en el 2020 es donde se presentan los mayores cambios comparativos y es efectivamente en donde se identifican crisis económicas que llevaron a la gente a buscar estas opciones de inversión.

plot(colones_ts_nd,type="l"); abline(h=0)

qqnorm(colones_ts_nd); qqline(colones_ts_nd)

acf(as.vector(colones_ts_nd))

pacf(as.vector(colones_ts_nd))

#Graficos para corroborar independencia(ruido blanco) que es diferente de correlaci?n (medida de dependencia lineal).
#Ho:residuos son independientes

acf(colones_ts_nd^2)

pacf(colones_ts_nd^2)


acf(abs(colones_ts_nd))

pacf(abs(colones_ts_nd))

En este caso algunas estacas se salen (algunas autocorrelaciones son significativas) y por tanto los rendimientos no son independientes ni identicamente distribuidos. Las autocorrelaciones significativas de los rendimientos al cuadrado o en términos absolutos reflejan la existencia de agrupamiento de volatilidad.

#McLeod.Li (Box-Ljung) test muestra una evidencia fuerte de heterocedasticidad condicional(p-value significativo). 
TSA::McLeod.Li.test(y=colones_ts_nd)

Además, a partir del test de McLeod.Li (Box-Ljung) se muestra evidencia fuerte de heterocedasticidad condicional ya que varios p-value son significativos.

3. Modelos

3.1 GARCH

garch_mod <- garchFit(~arma(0,0)+garch(1,1), data=colones_ts_nd,include.mean = FALSE)

Series Initialization:
 ARMA Model:                arma
 Formula Mean:              ~ arma(0, 0)
 GARCH Model:               garch
 Formula Variance:          ~ garch(1, 1)
 ARMA Order:                0 0
 Max ARMA Order:            0
 GARCH Order:               1 1
 Max GARCH Order:           1
 Maximum Order:             1
 Conditional Dist:          norm
 h.start:                   2
 llh.start:                 1
 Length of Series:          144
 Recursion Init:            mci
 Series Scale:              0.09442756

Parameter Initialization:
 Initial Parameters:          $params
 Limits of Transformations:   $U, $V
 Which Parameters are Fixed?  $includes
 Parameter Matrix:
 Index List of Parameters to be Optimized:
 omega alpha1  beta1 
     2      3      5 
 Persistence:                  0.9 


--- START OF TRACE ---
Selected Algorithm: nlminb 

R coded nlminb Solver: 

  0:     205.31853: 0.100000 0.100000 0.800000
  1:     205.05745: 0.113718 0.0992421 0.808603
  2:     204.71236: 0.114358 0.0841662 0.802680
  3:     204.24204: 0.137742 0.0631733 0.810655
  4:     204.18557: 0.135547 0.0478989 0.803851
  5:     203.93132: 0.151239 0.0427123 0.807213
  6:     203.89114: 0.161898 0.0318781 0.799904
  7:     203.84106: 0.173784 0.0371834 0.789182
  8:     203.10394: 0.324904 0.0990070 0.574355
  9:     202.84014: 0.469831 0.0768479 0.444926
 10:     202.73039: 0.514836 0.108307 0.371814
 11:     202.73003: 0.507096 0.119596 0.389938
 12:     202.71155: 0.498334 0.115897 0.389702
 13:     202.70982: 0.491146 0.117097 0.393875
 14:     202.70956: 0.489085 0.118707 0.394615
 15:     202.70956: 0.489077 0.118812 0.394661
 16:     202.70956: 0.489081 0.118814 0.394663

Final Estimate of the Negative LLH:
 LLH:  -137.1193    norm LLH:  -0.9522171 
      omega      alpha1       beta1 
0.004360923 0.118813794 0.394663285 

R-optimhess Difference Approximated Hessian Matrix:
             omega      alpha1       beta1
omega  -2735549.19 -15545.1878 -23464.3435
alpha1   -15545.19   -231.8720   -156.3857
beta1    -23464.34   -156.3857   -228.6424
attr(,"time")
Time difference of 0.005382061 secs

--- END OF TRACE ---


Time to Estimate Parameters:
 Time difference of 0.210856 secs
summary(garch_mod)

Title:
 GARCH Modelling 

Call:
 garchFit(formula = ~arma(0, 0) + garch(1, 1), data = colones_ts_nd, 
    include.mean = FALSE) 

Mean and Variance Equation:
 data ~ arma(0, 0) + garch(1, 1)
<environment: 0x7fed0da7baa8>
 [data = colones_ts_nd]

Conditional Distribution:
 norm 

Coefficient(s):
    omega     alpha1      beta1  
0.0043609  0.1188138  0.3946633  

Std. Errors:
 based on Hessian 

Error Analysis:
        Estimate  Std. Error  t value Pr(>|t|)  
omega   0.004361    0.001753    2.488   0.0128 *
alpha1  0.118814    0.089755    1.324   0.1856  
beta1   0.394663    0.205519    1.920   0.0548 .
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Log Likelihood:
 137.1193    normalized:  0.9522171 

Description:
 Thu Sep 10 20:06:30 2020 by user:  


Standardised Residuals Tests:
                                Statistic p-Value     
 Jarque-Bera Test   R    Chi^2  9.301433  0.009554753 
 Shapiro-Wilk Test  R    W      0.9729107 0.00590049  
 Ljung-Box Test     R    Q(10)  33.06239  0.0002658874
 Ljung-Box Test     R    Q(15)  98.94819  2.065015e-14
 Ljung-Box Test     R    Q(20)  109.5676  2.353673e-14
 Ljung-Box Test     R^2  Q(10)  11.15519  0.3455557   
 Ljung-Box Test     R^2  Q(15)  41.28482  0.0002893284
 Ljung-Box Test     R^2  Q(20)  44.75268  0.001191913 
 LM Arch Test       R    TR^2   32.64833  0.00109813  

Information Criterion Statistics:
      AIC       BIC       SIC      HQIC 
-1.862767 -1.800896 -1.863612 -1.837627 

3.1.1 - Chequeo del modelo

acf(residuals(garch_mod)^2)

pacf(residuals(garch_mod)^2)

#1. Test de Portmanteu para residuos estandarizados al cuadrado donde la Ho es que los residuos no est?n correlacionados.

try(
gBox(garch_mod,method="absolut", plot = T)
)
Error in model$call : $ operator not defined for this S4 class

A partir de esta prueba y sumado a la inspección visual se determina que los residuos del modelo Garch estan correlacionados pues el p-value es mayor al punto de corte (0.05) y varias estacas en los gráficos son significativas.

fGarch::predict(garch_mod, n.ahead = 6,mse="uncond",plot=TRUE, crit_val=2)
NA

Por último, se observa que el ajuste del modelo en términos de predicción es muy deficiente.

3.2 Redes neuronales

nn_mod<-nnetar(colones_ts_nd)
summary(nn_mod)
          Length Class        Mode     
x         144    ts           numeric  
m           1    -none-       numeric  
p           1    -none-       numeric  
P           1    -none-       numeric  
scalex      2    -none-       list     
size        1    -none-       numeric  
subset    144    -none-       numeric  
model      20    nnetarmodels list     
nnetargs    0    -none-       list     
fitted    144    ts           numeric  
residuals 144    ts           numeric  
lags        8    -none-       numeric  
series      1    -none-       character
method      1    -none-       character
call        2    -none-       call     
acf(residuals(nn_mod)[!is.na(residuals(nn_mod))]^2)

pacf(residuals(nn_mod)[!is.na(residuals(nn_mod))]^2)

#1. Test de Portmanteu para residuos estandarizados al cuadrado donde la Ho es que los residuos no est?n correlacionados.

gBox(nn_mod,method="absolut", plot = T)

A partir de esta prueba y sumado a la inspección visual se determina que los residuos del modelo Garch estan correlacionados pues el p-value es mayor al punto de corte (0.05) y un par de estacas en los gráficos son significativas.

pred_nn_mod<-forecast::forecast(nn_mod,level = c(95), h=6, bootstrap=TRUE, npaths=10000)
pred_nn_mod

plot(pred_nn_mod)

Finalmente, se observa que aunque mejor que el modelo Garch, el modelo de redes neuronales tampoco tienen un buen ajuste en las predicciones.

3.3 Modelo autoregresivo aditivo no lineal

3.3.1 Encontrar dimensión de encrustación

dimension = estimateEmbeddingDim(colones_ts_nd, time.lag=1, max.embedding.dim=15,threshold=0.95, do.plot=TRUE)

3.3.2 Modelo

aar_mod <- aar(colones_ts_nd, m=dimension)
summary(aar_mod)

Non linear autoregressive model

AAR model

Family: gaussian 
Link function: identity 

Formula:
y ~ s(V1.0, bs = "cr") + s(V1..1, bs = "cr") + s(V1..2, bs = "cr") + 
    s(V1..3, bs = "cr") + s(V1..4, bs = "cr") + s(V1..5, bs = "cr") + 
    s(V1..6, bs = "cr") + s(V1..7, bs = "cr") + s(V1..8, bs = "cr")

Estimated degrees of freedom:
4.19 2.66 1.00 1.00 1.00 1.00 6.84 
5.27 1.00  total = 24.95 

GCV score: 0.007569904     

Residuals:
      Min        1Q    Median        3Q       Max 
-0.192080 -0.039738 -0.013724  0.038017  0.222674 

Fit:
residuals variance = 0.004716,  AIC = -607, MAPE = 1564%

Family: gaussian 
Link function: identity 

Formula:
y ~ s(V1.0, bs = "cr") + s(V1..1, bs = "cr") + s(V1..2, bs = "cr") + 
    s(V1..3, bs = "cr") + s(V1..4, bs = "cr") + s(V1..5, bs = "cr") + 
    s(V1..6, bs = "cr") + s(V1..7, bs = "cr") + s(V1..8, bs = "cr")

Parametric coefficients:
             Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.0083986  0.0067609  1.2422   0.2168

Approximate significance of smooth terms:
            edf Ref.df      F   p-value    
s(V1.0)  4.1897 4.9881 4.2915  0.001255 ** 
s(V1..1) 2.6568 3.3010 8.7961 2.236e-05 ***
s(V1..2) 1.0000 1.0000 0.8370  0.362243    
s(V1..3) 1.0000 1.0000 1.5514  0.215575    
s(V1..4) 1.0000 1.0000 0.9377  0.334995    
s(V1..5) 1.0000 1.0000 0.2848  0.594621    
s(V1..6) 6.8351 7.6297 1.0685  0.478906    
s(V1..7) 5.2686 6.0947 1.4614  0.198086    
s(V1..8) 1.0000 1.0000 2.2020  0.140692    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

R-sq.(adj) =  0.301   Deviance explained = 42.6%
GCV = 0.0075699  Scale est. = 0.0061709  n = 135
plot(aar_mod)

NA

NA

NA

NA

NA

NA

NA

NA

NA

NA

NA

3.3.3 Revision del modelo

e_aar_mod <- residuals(aar_mod)
plot(e_aar_mod)

e_aar_mod <- e_aar_mod[!is.na(e_aar_mod)]
acf(e_aar_mod)

pacf(e_aar_mod)

AIC(aar_mod)
[1] -607.3787
mse(aar_mod)
[1] 0.00471599
MAPE(aar_mod)
[1] 15.64393
#fitted(aar_mod)
#coef(aar_mod)
pred_aar <- predict(aar_mod, n.ahead=6)

autoplot(ts(c(colones_ts_nd, pred_aar), start = start(colones_ts_nd), frequency = frequency(colones_ts_nd)) )

Se observa que las medidas de ajuste (MSE y MAPE) no son malas y la predicción para los 6 periodos es mejor que el modelo Garch pero hay que comparar con los demás para determinar cual obtiene mejor ajuste.

3.4 Modelo STAR (Smooth Transition AutoRegressive)

star_mod <- star(colones_ts_nd, mTh=c(0,1), control=list(maxit=10000))
Testing linearity...   p-Value =  0.1093008 
The series is linear. Using linear model instead.
summary(star_mod)

Non linear autoregressive model

AR model
Coefficients:
      const       phi.1       phi.2 
 0.01003181 -0.27505109 -0.36784039 

Residuals:
         Min           1Q       Median           3Q          Max 
-0.239698053 -0.055424235 -0.003978698  0.052357091  0.235607211 

Fit:
residuals variance = 0.007303,  AIC = -702, MAPE = 229.3%

Coefficient(s):
        Estimate  Std. Error  t value  Pr(>|t|)    
const  0.0100318   0.0072786   1.3783 0.1703347    
phi.1 -0.2750511   0.0797298  -3.4498 0.0007431 ***
phi.2 -0.3678404   0.0793699  -4.6345 8.153e-06 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
plot(star_mod)

NA

NA

e_star_mod <- residuals(star_mod)
plot(e_star_mod)

e_star_mod <- e_star_mod[!is.na(e_star_mod)]
acf(e_star_mod)

pacf(e_star_mod)


AIC(star_mod)
[1] -702.4032
mse(star_mod)
[1] 0.007303027
MAPE(star_mod)
[1] 2.292716


pred_star <- predict(star_mod, n.ahead=6)

Los indicadores del modelo Star son mejores que los del modelo Aar, tanto el AIC, como el MSE y MAPE. Los resultados del pronóstico son similares entre los 2 modelos y es por esta razón que se procede a revisar los pronósticos de todos los modelos no lineales para determinar el mejor.

4 - Selección del mejor modelo

Una vez teniendo los modelos de suavizamiento exponencial, de regresión y Box-Jenkings (ARIMA) se procede a compararlos en términos de ajuste visual y de indicadores de ajuste para determinar cual es el mejor modelo que pronostique el número de muertes por accidentes de tránsito en Costa Rica.

# Prediccion redes neuronales
f_mod1 <-
  exp(
      log(colones_ts[145]) + cumsum(pred_nn_mod$mean)
    )

f_mod1_ts = ts(
  f_mod1,
  frequency = 12,
  start = c(2020, 2),
  end = c(2020, 7)
)

# Prediccion modelo aar
f_mod2 <-
  exp(
      log(colones_ts[145]) + cumsum(pred_aar)
    )

f_mod2_ts = ts(
  f_mod2,
  frequency = 12,
  start = c(2020, 2),
  end = c(2020, 7)
)

# Prediccion modelo Star
f_mod3 <-
  exp(
      log(colones_ts[145]) + cumsum(pred_star)
    )

f_mod3_ts = ts(
  f_mod3,
  frequency = 12,
  start = c(2020, 2),
  end = c(2020, 7)
)


todos_preds <- cbind(
  Serie = colones_ts,
  Real = colones_ts_val,
  Prediccion1 = f_mod1_ts,
  Prediccion2 = f_mod2_ts,
  Prediccion3 = f_mod3_ts
)

# Graficamos
dygraph(todos_preds, main = "Predicción todos los modelos") %>%
dySeries("Serie", label = "Cantidad") %>%
dySeries("Real", label = "Real") %>%
#dySeries("Prediccion1", label = "SES") %>%
#dySeries("Prediccion2", label = "Holt") %>%
dySeries("Prediccion1", label = "Red_neuronal") %>%
dySeries("Prediccion2", label = "AAR") %>%
dySeries("Prediccion3", label = "STAR") %>%
dyAxis("x", label = "Meses") %>% 
dyAxis("y", label = "Accidentes") %>% 
dyOptions(colors = RColorBrewer::brewer.pal(7, "Set1")) %>% 
dyRangeSelector()



acc_todos <- tibble(
  Metodo = c("Red_neuronal", "AAR", "STAR"),
  RMSE = round(
    c(
      forecast::accuracy(f_mod1_ts, colones_ts_val)[2],
      forecast::accuracy(f_mod2_ts, colones_ts_val)[2],
      forecast::accuracy(f_mod3_ts, colones_ts_val)[2]
    ),
    3
  ),
  MAE = round(
    c(
      forecast::accuracy(f_mod1_ts, colones_ts_val)[3],
      forecast::accuracy(f_mod2_ts, colones_ts_val)[3],
      forecast::accuracy(f_mod3_ts, colones_ts_val)[3]
    ),
    3
  ),
  MAPE = round(
    c(
      forecast::accuracy(f_mod1_ts, colones_ts_val)[5],
      forecast::accuracy(f_mod2_ts, colones_ts_val)[5],
      forecast::accuracy(f_mod3_ts, colones_ts_val)[5]
    ),
    3
  )
) 

acc_todos %>% 
  mutate_if(is.numeric, function(x) {
    cell_spec(x, bold = T, 
              color = spec_color(x, end = 0.9, direction = -1),
              font_size = spec_font_size(x, begin = 12,end = 14, scale_from = NA))
  }) %>%
  kable(escape = F, caption = "Medidas de ajuste (Todos los modelos)", digits = 2) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed", "responsive"))

Medidas de ajuste (Todos los modelos)
Metodo RMSE MAE MAPE
Red_neuronal 85345.238 66959.819 8.262
AAR 105139.802 88869.341 10.584
STAR 104337.547 88241.358 9.81

NA

Finalmente, se obtienen los valores de pronostico de 3 modelos a contrastar: Red neuronal, AAR y STAR. Se puede apreciar que el STAR fue el mas alejado de los valores reales. Entre los otros modelos se puede observar que tienen, en términos gráficos, resultados similares aunque difieren al final del periodo de prueba donde la red neuronal ajusta mejor. Moviendonos al análisis de los indicadores de ajuste se puede ver que la red neuronal fue el modelo que obtuvo los mejores indicadores y es entonces que se selecciona como el mejor modelo no lineal para predecir el número de autos importados por mes en Costa Rica.

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3J9CmxpYnJhcnkoaGVyZSkKbGlicmFyeShyZWFkeGwpCiNsaWJyYXJ5KHBhcGVSKQojbGlicmFyeShvdXRsaWVycykKbGlicmFyeShrYWJsZUV4dHJhKQojbGlicmFyeShEYXRhRXhwbG9yZXIpCmxpYnJhcnkobHVicmlkYXRlKQpsaWJyYXJ5KGZvcmVjYXN0KQpsaWJyYXJ5KG5sbWUpCiNsaWJyYXJ5KG5vcnRlc3QpCmxpYnJhcnkoZ2dmb3J0aWZ5KQpsaWJyYXJ5KGR5Z3JhcGhzKQojbGlicmFyeShzZWFzb25hbCkKI2xpYnJhcnkoc2Vhc29uYWx2aWV3KQoKbGlicmFyeShub25saW5lYXJUc2VyaWVzKQpsaWJyYXJ5KGZOb25saW5lYXIpCmxpYnJhcnkoZkdhcmNoKQpsaWJyYXJ5KFRTQSkKbGlicmFyeSh0c0R5bikKCmxpYnJhcnkodGlkeXZlcnNlKQoKYGBgCgpSdXRhcwpgYGB7cn0KcmF3X2RhdGEgPC0gaGVyZSgiZGF0YSIsICJyYXciKQppbnRlcmltX2RhdGEgPC0gaGVyZSgiZGF0YSIsICJpbnRlcmltIikKZmluYWxfZGF0YSA8LSBoZXJlKCJkYXRhIiwgInByb2Nlc3NlZCIpCgpgYGAKCkxleWVuZG8gYmFzZSBkZSBkYXRvcwpgYGB7cn0KYmFzZSA8LSByZWFkX2V4Y2VsKHBhc3RlMChyYXdfZGF0YSwiL0Jhc2UgRGF0b3MueGxzeCIpLCAKICAgIGNvbF90eXBlcyA9IGMoInRleHQiLCAibnVtZXJpYyIsICJudW1lcmljIikpCgpoZWFkKGJhc2UpCmBgYAoKRXh0cmF5ZW5kbyBsYSBiYXNlIGRlIGNvbG9uZXMgeSBkZSBkb2xhcmVzCmBgYHtyfQoKY29sb25lcyA8LSBkYXRhX2ZyYW1lKGRhdGUgPSBiYXNlJGBBY3Rpdm8gbmV0b2AsCiAgICAgICAgICAgICAgICAgIGNvbCA9ICBhcy5kb3VibGUoYmFzZSRDUkMpKSAlPiUKICBtdXRhdGUoZGF0ZSA9IHltZChwYXN0ZTAoZGF0ZSwgIi0wMSIpKSkgJT4lCiAgbXV0YXRlKHllYXIgPSBhcy5mYWN0b3IoeWVhcihkYXRlKSksCiAgICAgICAgIG1vbnRoID0gYXMuZmFjdG9yKG1vbnRoKGRhdGUpKSkKCmhlYWQoY29sb25lcykKYGBgCgpDb252aXJ0aWVuZG8gbG9zIGRhdG9zIGEgc2VyaWVzIGRlIHRpZW1wbwpgYGB7cn0KIyBDb2xvbmVzCgojIDYgcGVyaW9kb3MgcGFyYSB1dGlsaXphciBhIG1vZG8gZGUgdmFsaWRhY2nDs24KY29sb25lc192YWwgPC0gY29sb25lcyAlPiUgCiAgc2xpY2VfdGFpbChuID0gNikKCiMgU2VyaWUgY29tcGxldGEgcGFyYSBlbCBhbmFsaXNpcyBleHBsb3JhdG9yaW8KY29sb25lc19mdWxsIDwtIGNvbG9uZXMKCiMgMTAgYcOxb3MgZGUgZGF0b3MgcGFyYSBtb2RlbGFyCmNvbG9uZXMgPC0gY29sb25lcyAlPiUgCiAgZmlsdGVyKGRhdGU+IjIwMDctMTItMDEiICYgZGF0ZTw9IjIwMjAtMDEtMDEiKQoKIyBPYmpldG9zIHRzIHRhbnRvIHBhcmEgbGEgc2VyaWUgY29tcGxldGEgY29tbyBwYXJhIGxhIHNlcmllIGRlIG1vZGVsYWRvCmNvbG9uZXNfdHNfZnVsbCA8LSB0cyhjb2xvbmVzX2Z1bGwkY29sLCBzdGFydCA9IGMoMjAwMSwyKSwgZnJlcXVlbmN5ID0gMTIpCmNvbG9uZXNfdHMgPC0gdHMoY29sb25lcyRjb2wsIHN0YXJ0ID0gYygyMDA4LDEpLCBmcmVxdWVuY3kgPSAxMikKY29sb25lc190c192YWwgPC0gdGFpbChjb2xvbmVzX3RzX2Z1bGwsIDYpCgpgYGAKCiMgMSBDb21wcm9iYWNpb24gZGUgbGluZWFsaWRhZCBkZSBsYSBzZXJpZQoKIyMgMS4xIFBydWViYSBkZSBsaW5lYWxpZGFkIGRlIGxhIG1lZGlhCgpgYGB7cn0KCiMgTnVsbCBoeXBvdGhlc2lzOiBMaW5lYXJpdHkgaW4gIm1lYW4iCnRublRlc3QoY29sb25lc190cywgbGFnID0gMSwgdGl0bGUgPSBOVUxMLCBkZXNjcmlwdGlvbiA9IE5VTEwpCgpgYGAKTGEgaGlww7N0ZXNpcyBudWxhIGRlbCBUZXJhZXN2aXJ0YSBOZXVyYWwgTmV0d29yayBUZXN0IGVzIHF1ZSBsYSBtZWRpYSBkZSBsYSBzZXJpZSBlcyBsaW5lYWwuIEFsIHJlY2hhemFyc2UgbGEgaGlww7N0ZXNpcyBjb24gdW5hIGNvbmZpYW56YSBkZWwgOTUlIHNlIHB1ZWRlIGRlY2lyIHF1ZSBsYSBzZXJpZSBlcyBubyBsaW5lYWwuCgojIDEuMiBQcnVlYmEgcGFyYSBkZXRlcm1pbmFyIHNpIGVzIGNhb3RpY2EgbyBubwoKYGBge3J9Cm9wdGlvbnMobWF4LnByaW50PTEwMDAwMDApCnJxYS5hbmFseXNpcz1ycWEodGltZS5zZXJpZXMgPSBjb2xvbmVzX3RzLCBlbWJlZGRpbmcuZGltPTEsIHRpbWUubGFnPTEscmFkaXVzPTAuMDEsbG1pbj0yLHZtaW49Mixkby5wbG90PVRSVUUsZGlzdGFuY2VUb0JvcmRlcj0yKQoKYGBgCiMgMi4gSW5zcGVjY2nDs24KYGBge3J9CiMgVW5hIGZvcm1hIHZpc3VhbCBkZSBlbXBlemFyIGEgcmV2aXNhciBzaSBleGlzdGVuIG8gbm8gY2x1c3RlcnMgZGUgdm9sYXRpbGlkYWQgCgpjb2xvbmVzX3RzX25kIDwtZGlmZihsb2coY29sb25lc190cykpCgoKY29sb25lc190c19uZDI8LWNvbG9uZXNfdHNfbmQtbWVhbihjb2xvbmVzX3RzX25kKSAjIEVzIGVsIGNhbWJpbyByZWxhdGl2byBhanVzdGFkbyBwb3IgbGEgbWVkaWEgZW4gZWwgdGlwbyBkZSBjYW1iaW8gCiNjb2xvbmVzX3RzX25kMgoKY29sb25lc190c19uZDM8LWNvbG9uZXNfdHNfbmQyXjIgIyBNZWRpZGEgZGUgbGEgdm9sYXRpbGlkYWQuIEFsIHNlciB1bmEgY2FudGlkYWQgYWwgY3VhZHJhZG8sIHN1IHZhbG9yIHNlcj8gYWx0byBlbiBwZXJpb2RvcyBlbiBxdWUgc2UgZXhwZXJpbWVudGVuIGdyYW5kZXMgY2FtYmlvcyAgeSBjb21wYXJhdGl2YW1lbnRlIHBlcXVlP28gY3VhbmRvIHN1Y2VkYW4gY2FtYmlvcyBtb2Rlc3RvcyBlbiBsb3MgcHJlY2lvcyBkZSBkaWNob3MgYmllbmVzLiAKCnBsb3QoY29sb25lc190c19uZDMpCmBgYAoKRW4gZXN0ZSBncsOhZmljbyBkZSBsYSBzZXJpZSBhanVzdGFkYSBwb3IgbGEgbWVkaWEgeSBlbGV2YWRhIGFsIGN1YWRyYWRvIHNlIHByZXRlbmRlIG9ic2VydmFyIApsYSB2b2xhdGlsaWRhZCBkZSBsYSBtaXNtYS4gQWwgc2VyIHVuYSBjYW50aWRhZCBhbCBjdWFkcmFkbywgY3VhbmRvIHN1IHZhbG9yIHNlcyBhbHRvIGVuIGluZGljYSBxdWUgc2UgZXhwZXJpbWVudGVuIGdyYW5kZXMgY2FtYmlvcyAgeSBjb21wYXJhdGl2YW1lbnRlIHBlcXVlw7FvIGN1YW5kbyBzdWNlZGFuIGNhbWJpb3MgbW9kZXN0b3MgZW4gbG9zIHByZWNpb3MgZGUgZGljaG9zIGJpZW5lcy4gRXMgYXPDrSBxdWUgZXMgY2xhcm8gcXVlIGRlc3B1w6lzIGRlbCAyMDA4LCBhbHJlZGVkb3IgZGVsIDIwMTQgeSBlbiBlbCAyMDIwIGVzCmRvbmRlIHNlIHByZXNlbnRhbiBsb3MgbWF5b3JlcyBjYW1iaW9zIGNvbXBhcmF0aXZvcyB5IGVzIGVmZWN0aXZhbWVudGUgZW4gZG9uZGUgc2UgCmlkZW50aWZpY2FuIGNyaXNpcyBlY29uw7NtaWNhcyBxdWUgbGxldmFyb24gYSBsYSBnZW50ZSBhIGJ1c2NhciBlc3RhcyBvcGNpb25lcyBkZSBpbnZlcnNpw7NuLiAKCmBgYHtyfQpwbG90KGNvbG9uZXNfdHNfbmQsdHlwZT0ibCIpOyBhYmxpbmUoaD0wKQpxcW5vcm0oY29sb25lc190c19uZCk7IHFxbGluZShjb2xvbmVzX3RzX25kKQphY2YoYXMudmVjdG9yKGNvbG9uZXNfdHNfbmQpKQpwYWNmKGFzLnZlY3Rvcihjb2xvbmVzX3RzX25kKSkKCmBgYAoKYGBge3J9CiNHcmFmaWNvcyBwYXJhIGNvcnJvYm9yYXIgaW5kZXBlbmRlbmNpYShydWlkbyBibGFuY28pIHF1ZSBlcyBkaWZlcmVudGUgZGUgY29ycmVsYWNpP24gKG1lZGlkYSBkZSBkZXBlbmRlbmNpYSBsaW5lYWwpLgojSG86cmVzaWR1b3Mgc29uIGluZGVwZW5kaWVudGVzCgphY2YoY29sb25lc190c19uZF4yKQpwYWNmKGNvbG9uZXNfdHNfbmReMikKCmFjZihhYnMoY29sb25lc190c19uZCkpCnBhY2YoYWJzKGNvbG9uZXNfdHNfbmQpKQpgYGAKCkVuIGVzdGUgY2FzbyBhbGd1bmFzIGVzdGFjYXMgc2Ugc2FsZW4gKGFsZ3VuYXMgYXV0b2NvcnJlbGFjaW9uZXMgc29uIHNpZ25pZmljYXRpdmFzKSB5IHBvciB0YW50byBsb3MgcmVuZGltaWVudG9zIG5vIHNvbiBpbmRlcGVuZGllbnRlcyBuaSBpZGVudGljYW1lbnRlIGRpc3RyaWJ1aWRvcy4KTGFzIGF1dG9jb3JyZWxhY2lvbmVzIHNpZ25pZmljYXRpdmFzIGRlIGxvcyByZW5kaW1pZW50b3MgYWwgY3VhZHJhZG8gbyBlbiB0w6lybWlub3MgYWJzb2x1dG9zIHJlZmxlamFuIGxhIGV4aXN0ZW5jaWEgZGUgYWdydXBhbWllbnRvIGRlIHZvbGF0aWxpZGFkLgoKYGBge3J9CiNNY0xlb2QuTGkgKEJveC1ManVuZykgdGVzdCBtdWVzdHJhIHVuYSBldmlkZW5jaWEgZnVlcnRlIGRlIGhldGVyb2NlZGFzdGljaWRhZCBjb25kaWNpb25hbChwLXZhbHVlIHNpZ25pZmljYXRpdm8pLiAKVFNBOjpNY0xlb2QuTGkudGVzdCh5PWNvbG9uZXNfdHNfbmQpCgpgYGAKIEFkZW3DoXMsIGEgcGFydGlyIGRlbCB0ZXN0IGRlIE1jTGVvZC5MaSAoQm94LUxqdW5nKSBzZSBtdWVzdHJhIGV2aWRlbmNpYSBmdWVydGUgZGUgaGV0ZXJvY2VkYXN0aWNpZGFkIGNvbmRpY2lvbmFsIHlhIHF1ZSB2YXJpb3MgcC12YWx1ZSBzb24gc2lnbmlmaWNhdGl2b3MuCiAKIyAzLiBNb2RlbG9zCgojIyAzLjEgR0FSQ0gKCmBgYHtyfQpnYXJjaF9tb2QgPC0gZ2FyY2hGaXQofmFybWEoMCwwKStnYXJjaCgxLDEpLCBkYXRhPWNvbG9uZXNfdHNfbmQsaW5jbHVkZS5tZWFuID0gRkFMU0UpCgpzdW1tYXJ5KGdhcmNoX21vZCkKYGBgCgojIyMgMy4xLjEgLSBDaGVxdWVvIGRlbCBtb2RlbG8KCmBgYHtyfQphY2YocmVzaWR1YWxzKGdhcmNoX21vZCleMikKcGFjZihyZXNpZHVhbHMoZ2FyY2hfbW9kKV4yKQoKYGBgCgpgYGB7cn0KIzEuIFRlc3QgZGUgUG9ydG1hbnRldSBwYXJhIHJlc2lkdW9zIGVzdGFuZGFyaXphZG9zIGFsIGN1YWRyYWRvIGRvbmRlIGxhIEhvIGVzIHF1ZSBsb3MgcmVzaWR1b3Mgbm8gZXN0P24gY29ycmVsYWNpb25hZG9zLgoKdHJ5KApnQm94KGdhcmNoX21vZCxtZXRob2Q9ImFic29sdXQiLCBwbG90ID0gVCkKKQoKYGBgCiAKIEEgcGFydGlyIGRlIGVzdGEgcHJ1ZWJhIHkgc3VtYWRvIGEgbGEgaW5zcGVjY2nDs24gdmlzdWFsIHNlIGRldGVybWluYSBxdWUgbG9zIHJlc2lkdW9zIGRlbCBtb2RlbG8gR2FyY2ggZXN0YW4gY29ycmVsYWNpb25hZG9zIHB1ZXMgZWwgcC12YWx1ZSBlcyBtYXlvciBhbCBwdW50byBkZSBjb3J0ZSAoMC4wNSkgeSB2YXJpYXMgZXN0YWNhcyBlbiBsb3MKIGdyw6FmaWNvcyBzb24gc2lnbmlmaWNhdGl2YXMuCiAKYGBge3J9CmZHYXJjaDo6cHJlZGljdChnYXJjaF9tb2QsIG4uYWhlYWQgPSA2LG1zZT0idW5jb25kIixwbG90PVRSVUUsIGNyaXRfdmFsPTIpCgpgYGAKIFBvciDDumx0aW1vLCBzZSBvYnNlcnZhIHF1ZSBlbCBhanVzdGUgZGVsIG1vZGVsbyBlbiB0w6lybWlub3MgZGUgcHJlZGljY2nDs24gZXMgbXV5IGRlZmljaWVudGUuCiAKIyMgMy4yIFJlZGVzIG5ldXJvbmFsZXMKIApgYGB7cn0Kbm5fbW9kPC1ubmV0YXIoY29sb25lc190c19uZCkKc3VtbWFyeShubl9tb2QpCgpgYGAKCgpgYGB7cn0KYWNmKHJlc2lkdWFscyhubl9tb2QpWyFpcy5uYShyZXNpZHVhbHMobm5fbW9kKSldXjIpCnBhY2YocmVzaWR1YWxzKG5uX21vZClbIWlzLm5hKHJlc2lkdWFscyhubl9tb2QpKV1eMikKCmBgYApgYGB7cn0KIzEuIFRlc3QgZGUgUG9ydG1hbnRldSBwYXJhIHJlc2lkdW9zIGVzdGFuZGFyaXphZG9zIGFsIGN1YWRyYWRvIGRvbmRlIGxhIEhvIGVzIHF1ZSBsb3MgcmVzaWR1b3Mgbm8gZXN0P24gY29ycmVsYWNpb25hZG9zLgoKZ0JveChubl9tb2QsbWV0aG9kPSJhYnNvbHV0IiwgcGxvdCA9IFQpCgpgYGAKIAogQSBwYXJ0aXIgZGUgZXN0YSBwcnVlYmEgeSBzdW1hZG8gYSBsYSBpbnNwZWNjacOzbiB2aXN1YWwgc2UgZGV0ZXJtaW5hIHF1ZSBsb3MgcmVzaWR1b3MgZGVsIG1vZGVsbyBHYXJjaCBlc3RhbiBjb3JyZWxhY2lvbmFkb3MgcHVlcyBlbCBwLXZhbHVlIGVzIG1heW9yIGFsIHB1bnRvIGRlIGNvcnRlICgwLjA1KSB5IHVuIHBhciBkZSBlc3RhY2FzIGVuIGxvcwogZ3LDoWZpY29zIHNvbiBzaWduaWZpY2F0aXZhcy4KCmBgYHtyfQpwcmVkX25uX21vZDwtZm9yZWNhc3Q6OmZvcmVjYXN0KG5uX21vZCxsZXZlbCA9IGMoOTUpLCBoPTYsIGJvb3RzdHJhcD1UUlVFLCBucGF0aHM9MTAwMDApCnByZWRfbm5fbW9kCgpwbG90KHByZWRfbm5fbW9kKQpgYGAKRmluYWxtZW50ZSwgc2Ugb2JzZXJ2YSBxdWUgYXVucXVlIG1lam9yIHF1ZSBlbCBtb2RlbG8gR2FyY2gsIGVsIG1vZGVsbyBkZSByZWRlcyBuZXVyb25hbGVzCnRhbXBvY28gdGllbmVuIHVuIGJ1ZW4gYWp1c3RlIGVuIGxhcyBwcmVkaWNjaW9uZXMuIAoKIyMgMy4zIE1vZGVsbyBhdXRvcmVncmVzaXZvIGFkaXRpdm8gbm8gbGluZWFsCgojIyMgMy4zLjEgRW5jb250cmFyIGRpbWVuc2nDs24gZGUgZW5jcnVzdGFjacOzbgoKYGBge3J9CmRpbWVuc2lvbiA9IGVzdGltYXRlRW1iZWRkaW5nRGltKGNvbG9uZXNfdHNfbmQsIHRpbWUubGFnPTEsIG1heC5lbWJlZGRpbmcuZGltPTE1LHRocmVzaG9sZD0wLjk1LCBkby5wbG90PVRSVUUpCgpgYGAKIyMjIDMuMy4yIE1vZGVsbwpgYGB7cn0KYWFyX21vZCA8LSBhYXIoY29sb25lc190c19uZCwgbT1kaW1lbnNpb24pCnN1bW1hcnkoYWFyX21vZCkKcGxvdChhYXJfbW9kKQoKYGBgCiMjIyAzLjMuMyBSZXZpc2lvbiBkZWwgbW9kZWxvCgpgYGB7cn0KZV9hYXJfbW9kIDwtIHJlc2lkdWFscyhhYXJfbW9kKQpwbG90KGVfYWFyX21vZCkKZV9hYXJfbW9kIDwtIGVfYWFyX21vZFshaXMubmEoZV9hYXJfbW9kKV0KYWNmKGVfYWFyX21vZCkKcGFjZihlX2Fhcl9tb2QpCgpgYGAKCmBgYHtyfQpBSUMoYWFyX21vZCkKbXNlKGFhcl9tb2QpCk1BUEUoYWFyX21vZCkKI2ZpdHRlZChhYXJfbW9kKQojY29lZihhYXJfbW9kKQoKYGBgCgoKYGBge3J9CnByZWRfYWFyIDwtIHByZWRpY3QoYWFyX21vZCwgbi5haGVhZD02KQoKYXV0b3Bsb3QodHMoYyhjb2xvbmVzX3RzX25kLCBwcmVkX2FhciksIHN0YXJ0ID0gc3RhcnQoY29sb25lc190c19uZCksIGZyZXF1ZW5jeSA9IGZyZXF1ZW5jeShjb2xvbmVzX3RzX25kKSkgKQoKYGBgClNlIG9ic2VydmEgcXVlIGxhcyBtZWRpZGFzIGRlIGFqdXN0ZSAoTVNFIHkgTUFQRSkgbm8gc29uIG1hbGFzIHkgbGEgcHJlZGljY2nDs24gcGFyYSBsb3MgNiBwZXJpb2RvcwplcyBtZWpvciBxdWUgZWwgbW9kZWxvIEdhcmNoIHBlcm8gaGF5IHF1ZSBjb21wYXJhciBjb24gbG9zIGRlbcOhcyBwYXJhIGRldGVybWluYXIgY3VhbCBvYnRpZW5lIG1lam9yIGFqdXN0ZS4KCiMjIDMuNCBNb2RlbG8gU1RBUiAoU21vb3RoIFRyYW5zaXRpb24gQXV0b1JlZ3Jlc3NpdmUpCgoKCmBgYHtyfQpzdGFyX21vZCA8LSBzdGFyKGNvbG9uZXNfdHNfbmQsIG1UaD1jKDAsMSksIGNvbnRyb2w9bGlzdChtYXhpdD0xMDAwMCkpCnN1bW1hcnkoc3Rhcl9tb2QpCnBsb3Qoc3Rhcl9tb2QpCmBgYAoKCmBgYHtyfQplX3N0YXJfbW9kIDwtIHJlc2lkdWFscyhzdGFyX21vZCkKcGxvdChlX3N0YXJfbW9kKQplX3N0YXJfbW9kIDwtIGVfc3Rhcl9tb2RbIWlzLm5hKGVfc3Rhcl9tb2QpXQphY2YoZV9zdGFyX21vZCkKcGFjZihlX3N0YXJfbW9kKQpgYGAKCmBgYHtyfQpBSUMoc3Rhcl9tb2QpCm1zZShzdGFyX21vZCkKTUFQRShzdGFyX21vZCkKCgpgYGAKCgpgYGB7cn0KcHJlZF9zdGFyIDwtIHByZWRpY3Qoc3Rhcl9tb2QsIG4uYWhlYWQ9NikKCmF1dG9wbG90KHRzKGMoY29sb25lc190c19uZCwgcHJlZF9zdGFyKSwgc3RhcnQgPSBzdGFydChjb2xvbmVzX3RzX25kKSwgZnJlcXVlbmN5ID0gZnJlcXVlbmN5KGNvbG9uZXNfdHNfbmQpKSApCgpgYGAKCkxvcyBpbmRpY2Fkb3JlcyBkZWwgbW9kZWxvIFN0YXIgc29uIG1lam9yZXMgcXVlIGxvcyBkZWwgbW9kZWxvIEFhciwgdGFudG8gZWwgQUlDLCBjb21vIGVsIE1TRSB5IE1BUEUuIApMb3MgcmVzdWx0YWRvcyBkZWwgcHJvbsOzc3RpY28gc29uIHNpbWlsYXJlcyBlbnRyZSBsb3MgMiBtb2RlbG9zIHkgZXMgcG9yIGVzdGEgcmF6w7NuIHF1ZSBzZSBwcm9jZWRlIGEgCnJldmlzYXIgbG9zIHByb27Ds3N0aWNvcyBkZSB0b2RvcyBsb3MgbW9kZWxvcyBubyBsaW5lYWxlcyBwYXJhIGRldGVybWluYXIgZWwgbWVqb3IuIAoKIyA0IC0gU2VsZWNjacOzbiBkZWwgbWVqb3IgbW9kZWxvCgpVbmEgdmV6IHRlbmllbmRvIGxvcyBtb2RlbG9zIGRlIHN1YXZpemFtaWVudG8gZXhwb25lbmNpYWwsIGRlIHJlZ3Jlc2nDs24geSBCb3gtSmVua2luZ3MgKEFSSU1BKSBzZSBwcm9jZWRlIGEgY29tcGFyYXJsb3MgZW4gdMOpcm1pbm9zIGRlIGFqdXN0ZSB2aXN1YWwgeSBkZSBpbmRpY2Fkb3JlcyBkZSBhanVzdGUgcGFyYSBkZXRlcm1pbmFyIGN1YWwgZXMgZWwgbWVqb3IgbW9kZWxvIHF1ZSBwcm9ub3N0aXF1ZSBlbCBuw7ptZXJvIGRlIG11ZXJ0ZXMgcG9yIGFjY2lkZW50ZXMgZGUgdHLDoW5zaXRvIGVuIENvc3RhIFJpY2EuIAoKCmBgYHtyICB3YXJuaW5nPUZBTFNFfQojIFByZWRpY2Npb24gcmVkZXMgbmV1cm9uYWxlcwpmX21vZDEgPC0KICBleHAoCiAgICAgIGxvZyhjb2xvbmVzX3RzWzE0NV0pICsgY3Vtc3VtKHByZWRfbm5fbW9kJG1lYW4pCiAgICApCgpmX21vZDFfdHMgPSB0cygKICBmX21vZDEsCiAgZnJlcXVlbmN5ID0gMTIsCiAgc3RhcnQgPSBjKDIwMjAsIDIpLAogIGVuZCA9IGMoMjAyMCwgNykKKQoKIyBQcmVkaWNjaW9uIG1vZGVsbyBhYXIKZl9tb2QyIDwtCiAgZXhwKAogICAgICBsb2coY29sb25lc190c1sxNDVdKSArIGN1bXN1bShwcmVkX2FhcikKICAgICkKCmZfbW9kMl90cyA9IHRzKAogIGZfbW9kMiwKICBmcmVxdWVuY3kgPSAxMiwKICBzdGFydCA9IGMoMjAyMCwgMiksCiAgZW5kID0gYygyMDIwLCA3KQopCgojIFByZWRpY2Npb24gbW9kZWxvIFN0YXIKZl9tb2QzIDwtCiAgZXhwKAogICAgICBsb2coY29sb25lc190c1sxNDVdKSArIGN1bXN1bShwcmVkX3N0YXIpCiAgICApCgpmX21vZDNfdHMgPSB0cygKICBmX21vZDMsCiAgZnJlcXVlbmN5ID0gMTIsCiAgc3RhcnQgPSBjKDIwMjAsIDIpLAogIGVuZCA9IGMoMjAyMCwgNykKKQoKCnRvZG9zX3ByZWRzIDwtIGNiaW5kKAogIFNlcmllID0gY29sb25lc190cywKICBSZWFsID0gY29sb25lc190c192YWwsCiAgUHJlZGljY2lvbjEgPSBmX21vZDFfdHMsCiAgUHJlZGljY2lvbjIgPSBmX21vZDJfdHMsCiAgUHJlZGljY2lvbjMgPSBmX21vZDNfdHMKKQoKIyBHcmFmaWNhbW9zCmR5Z3JhcGgodG9kb3NfcHJlZHMsIG1haW4gPSAiUHJlZGljY2nDs24gdG9kb3MgbG9zIG1vZGVsb3MiKSAlPiUKZHlTZXJpZXMoIlNlcmllIiwgbGFiZWwgPSAiRW50cmVuYW1pZW50byIpICU+JQpkeVNlcmllcygiUmVhbCIsIGxhYmVsID0gIlBydWViYSIpICU+JQojZHlTZXJpZXMoIlByZWRpY2Npb24xIiwgbGFiZWwgPSAiU0VTIikgJT4lCiNkeVNlcmllcygiUHJlZGljY2lvbjIiLCBsYWJlbCA9ICJIb2x0IikgJT4lCmR5U2VyaWVzKCJQcmVkaWNjaW9uMSIsIGxhYmVsID0gIlJlZF9uZXVyb25hbCIpICU+JQpkeVNlcmllcygiUHJlZGljY2lvbjIiLCBsYWJlbCA9ICJBQVIiKSAlPiUKZHlTZXJpZXMoIlByZWRpY2Npb24zIiwgbGFiZWwgPSAiU1RBUiIpICU+JQpkeUF4aXMoIngiLCBsYWJlbCA9ICJNZXNlcyIpICU+JSAKZHlBeGlzKCJ5IiwgbGFiZWwgPSAiTW9udG9zIChDT0wpIikgJT4lIApkeU9wdGlvbnMoY29sb3JzID0gUkNvbG9yQnJld2VyOjpicmV3ZXIucGFsKDcsICJTZXQxIikpICU+JSAKZHlSYW5nZVNlbGVjdG9yKCkKCgphY2NfdG9kb3MgPC0gdGliYmxlKAogIE1ldG9kbyA9IGMoIlJlZF9uZXVyb25hbCIsICJBQVIiLCAiU1RBUiIpLAogIFJNU0UgPSByb3VuZCgKICAgIGMoCiAgICAgIGZvcmVjYXN0OjphY2N1cmFjeShmX21vZDFfdHMsIGNvbG9uZXNfdHNfdmFsKVsyXSwKICAgICAgZm9yZWNhc3Q6OmFjY3VyYWN5KGZfbW9kMl90cywgY29sb25lc190c192YWwpWzJdLAogICAgICBmb3JlY2FzdDo6YWNjdXJhY3koZl9tb2QzX3RzLCBjb2xvbmVzX3RzX3ZhbClbMl0KICAgICksCiAgICAzCiAgKSwKICBNQUUgPSByb3VuZCgKICAgIGMoCiAgICAgIGZvcmVjYXN0OjphY2N1cmFjeShmX21vZDFfdHMsIGNvbG9uZXNfdHNfdmFsKVszXSwKICAgICAgZm9yZWNhc3Q6OmFjY3VyYWN5KGZfbW9kMl90cywgY29sb25lc190c192YWwpWzNdLAogICAgICBmb3JlY2FzdDo6YWNjdXJhY3koZl9tb2QzX3RzLCBjb2xvbmVzX3RzX3ZhbClbM10KICAgICksCiAgICAzCiAgKSwKICBNQVBFID0gcm91bmQoCiAgICBjKAogICAgICBmb3JlY2FzdDo6YWNjdXJhY3koZl9tb2QxX3RzLCBjb2xvbmVzX3RzX3ZhbClbNV0sCiAgICAgIGZvcmVjYXN0OjphY2N1cmFjeShmX21vZDJfdHMsIGNvbG9uZXNfdHNfdmFsKVs1XSwKICAgICAgZm9yZWNhc3Q6OmFjY3VyYWN5KGZfbW9kM190cywgY29sb25lc190c192YWwpWzVdCiAgICApLAogICAgMwogICkKKSAKCmFjY190b2RvcyAlPiUgCiAgbXV0YXRlX2lmKGlzLm51bWVyaWMsIGZ1bmN0aW9uKHgpIHsKICAgIGNlbGxfc3BlYyh4LCBib2xkID0gVCwgCiAgICAgICAgICAgICAgY29sb3IgPSBzcGVjX2NvbG9yKHgsIGVuZCA9IDAuOSwgZGlyZWN0aW9uID0gLTEpLAogICAgICAgICAgICAgIGZvbnRfc2l6ZSA9IHNwZWNfZm9udF9zaXplKHgsIGJlZ2luID0gMTIsZW5kID0gMTQsIHNjYWxlX2Zyb20gPSBOQSkpCiAgfSkgJT4lCiAga2FibGUoZXNjYXBlID0gRiwgY2FwdGlvbiA9ICJNZWRpZGFzIGRlIGFqdXN0ZSAoVG9kb3MgbG9zIG1vZGVsb3MpIiwgZGlnaXRzID0gMikgJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIiwgInJlc3BvbnNpdmUiKSkKCmBgYAoKRmluYWxtZW50ZSwgc2Ugb2J0aWVuZW4gbG9zIHZhbG9yZXMgZGUgcHJvbm9zdGljbyBkZSAzIG1vZGVsb3MgYSBjb250cmFzdGFyOiBSZWQgbmV1cm9uYWwsIEFBUiB5IFNUQVIuIFNlIHB1ZWRlIGFwcmVjaWFyIHF1ZSBlbCBTVEFSIGZ1ZSBlbCBtYXMgYWxlamFkbyBkZSBsb3MgdmFsb3JlcyByZWFsZXMuIEVudHJlIGxvcyBvdHJvcyBtb2RlbG9zIHNlIHB1ZWRlIG9ic2VydmFyIHF1ZSB0aWVuZW4sIGVuIHTDqXJtaW5vcyBncsOhZmljb3MsIHJlc3VsdGFkb3Mgc2ltaWxhcmVzIGF1bnF1ZSBkaWZpZXJlbiBhbCBmaW5hbCBkZWwgcGVyaW9kbyBkZSBwcnVlYmEgZG9uZGUgbGEgcmVkIG5ldXJvbmFsIGFqdXN0YSBtZWpvci4gTW92aWVuZG9ub3MgYWwgYW7DoWxpc2lzIGRlIGxvcyBpbmRpY2Fkb3JlcyBkZSBhanVzdGUgc2UgcHVlZGUgdmVyIHF1ZSBsYSByZWQgbmV1cm9uYWwgZnVlIGVsIG1vZGVsbyBxdWUgb2J0dXZvIGxvcyBtZWpvcmVzIGluZGljYWRvcmVzICB5IGVzIGVudG9uY2VzIHF1ZSBzZSBzZWxlY2Npb25hIGNvbW8gZWwgbWVqb3IgbW9kZWxvIG5vIGxpbmVhbCBwYXJhIHByZWRlY2lyIGVsIG7Dum1lcm8gZGUgYXV0b3MgaW1wb3J0YWRvcyBwb3IgbWVzIGVuIENvc3RhIFJpY2EuIAoKCgoK